package sharemem

import (
	"log"
	"server_cluster/battle/battle_config"
	"server_cluster/common/tools"
)

const (
	BUFF_SUB_TYPE_ATTR		=	1
	BUFF_SUB_TYPE_DMG		=	2
	BUFF_SUB_TYPE_CURE		=	3
	BUFF_SUB_TYPE_STUN		=	4
	BUFF_SUB_TYPE_FREEZE	=	5
	BUFF_SUB_TYPE_SILENT	=	6
	BUFF_SUB_TYPE_ARMOR		=	7
	BUFF_SUB_TYPE_FREE		=	8
	BUFF_SUB_TYPE_HERO		=	9
	BUFF_SUB_TYPE_UNDEAD	=	10
	BUFF_SUB_TYPE_SHIELD	=	11
)

type Buff_have struct {
	id				int32
	Type			int8
	sub_type		int8
	group			int32		//组id
	grade			int8		//强度
	tag				int8		//tag
	loop_time		int32		//循环间隔
	next_time		int32		//下次执行时间
	end_time		int32		//结束时间
	level_max		int8
	level			int8		//层数
	level_func		int8		//层数公式
	total			int32		//总量
	base			[]int32		//基础数值
}
//获取属性修改基础值 属性id:值
func (target *Battle_unit)GetBuffChangeAttr(cfg *Buff) []int32 {
	var res []int32
	p1 := cfg.Param1
	if p1[1] == HP_REAL || p1[1] == ANGER_REAL || p1[1] == TOUGH_REAL {
		log.Printf("buff change attr id=%d error.",p1[1])
		return res
	}
	value := int32(0)
	switch p1[0] {
		case 1:
			value = target.TakeAtVal(VAL_INIT,p1[1])*p1[2]/10000
		case 2:
			value = p1[2]
	}
	res = append(res,p1[1],value)
	return res
}
//获取伤害值
func (cfg *Buff)GetBuffDmgValue(trigger *Battle_unit,target *Battle_unit) int32 {
    //基础值
    value := float32(0)
    switch cfg.Param1[0] {
        case 1:
            value = float32(trigger.TakeAtVal(VAL_MAX,ATK) * cfg.Param1[1]) / 10000
        case 2:
            value = float32(trigger.TakeAtVal(VAL_MAX,DEF) * cfg.Param1[1]) / 10000
        case 3:
            value = float32(trigger.TakeAtVal(VAL_MAX,HP) * cfg.Param1[1]) / 10000
        case 4:
            value = float32(target.TakeAtVal(VAL_MAX,ATK) * cfg.Param1[1]) / 10000
        case 5:
            value = float32(target.TakeAtVal(VAL_MAX,DEF) * cfg.Param1[1]) / 10000
        case 6:
            value = float32(target.TakeAtVal(VAL_MAX,HP) * cfg.Param1[1]) / 10000
		case 7:
			value = float32(cfg.Param1[1])
    }
    //log.Printf("value(%v)",value)
	//伤害结果增伤
	value *= (1 + float32(trigger.TakeAtVal(VAL_MAX,DOTDMG))/10000)
	//log.Printf("value(%v) attr_trigger.DOTDMG(%v)",value,trigger.TakeAtVal(DOTDMG))
	return int32(value)
}
//获取治疗值
func (cfg *Buff)GetBuffCureValue(trigger *Battle_unit,target *Battle_unit) int32 {
    //基础值
    value := float32(0)
    switch cfg.Param1[0] {
        case 1:
            value = float32(trigger.TakeAtVal(VAL_MAX,ATK) * cfg.Param1[1]) / 10000
        case 2:
            value = float32(trigger.TakeAtVal(VAL_MAX,DEF) * cfg.Param1[1]) / 10000
        case 3:
            value = float32(trigger.TakeAtVal(VAL_MAX,HP) * cfg.Param1[1]) / 10000
        case 4:
            value = float32(target.TakeAtVal(VAL_MAX,ATK) * cfg.Param1[1]) / 10000
        case 5:
            value = float32(target.TakeAtVal(VAL_MAX,DEF) * cfg.Param1[1]) / 10000
        case 6:
            value = float32(target.TakeAtVal(VAL_MAX,HP) * cfg.Param1[1]) / 10000
    }
    //log.Printf("value(%v)",value)
    //治疗量加成修正
    value *= (1 + (float32(trigger.TakeAtVal(VAL_MAX,CUREINC)) + float32(target.TakeAtVal(VAL_MAX,BECUREINC)))/10000)
    //log.Printf("value(%v) attr_trigger.CUREINC(%v) attr_target.BECUREINC(%v)",value,trigger.TakeAtVal(CUREINC),target.TakeAtVal(BECUREINC))

    //随机浮动修正
    value *= float32(tools.GetResultByRegion(battle_config.DMG_RANDOM_MIN,battle_config.DMG_RANDOM_MAX))/10000
    //log.Printf("cure rand-value(%v)",value)

    return int32(value)
}

//遍历check某单位所有buff
func (target *Battle_unit)CheckBuff() {
	all := target.GetAllBuffMap()
	//治疗buff优先生效
	del_cure := make([]int32,0)
	for k,v := range all[BUFF_SUB_TYPE_CURE] {
		if v.end_time <= target.area.root_time {
			//buff已结束
			target.BuffEndEvent(v)
			del_cure = append(del_cure,k)
		} else if v.next_time <= target.area.root_time {
			//循环执行
			target.DoBuffEffect(v)
		}
	}

	for _,v := range del_cure {
		delete(all[BUFF_SUB_TYPE_CURE],v)
	}
	//其它buff
	for k,v := range all {
		if k == BUFF_SUB_TYPE_CURE {
			continue
		}
		del := make([]int32,0)
		for k1,v1 := range v {
			if v1.end_time <= target.area.root_time {
				//buff已结束
				target.BuffEndEvent(v1)
				del = append(del,k1)
			} else if v1.next_time <= target.area.root_time {
				//循环执行
				target.DoBuffEffect(v1)
			}
		}
		for _,v1 := range del {
			delete(v,v1)
		}
	}
}

//循环执行某单位的某buff效果
func (target *Battle_unit)DoBuffEffect(buff *Buff_have) {
	switch buff.sub_type {
		case BUFF_SUB_TYPE_DMG:
			//伤害
			buff.next_time = target.area.root_time + buff.loop_time
			value := buff.total
			switch buff.level_func {
				case 1:
					value *= int32(buff.level)
			}
			target.DoHP(-value)
		case BUFF_SUB_TYPE_CURE:
			//治疗
			buff.next_time = target.area.root_time + buff.loop_time
			value := buff.total
			switch buff.level_func {
				case 1:
					value *= int32(buff.level)
			}
			target.DoHP(value)
		default:
			buff.next_time = buff.end_time
	}
	if buff.next_time < buff.end_time {
		target.area.SetEventMap(buff.next_time,0,0)
	}
}

//通过配置创建新buff 直接生效一次
func (cfg *Buff) CreateBuff(trigger *Battle_unit,target *Battle_unit,level int8) *Buff_have {
	var i int8
	var base []int32
	total := int32(0)
	switch cfg.Sub_type {
		case BUFF_SUB_TYPE_ATTR:
			//修改属性值
			base = target.GetBuffChangeAttr(cfg)
			if len(base) == 0 {
				log.Printf("get buff change attr error.")
				return nil
			}
			switch cfg.Level_func {
				case 1:
					base[1] *= int32(level)
			}
			total = base[1]
			target.ChangeAttr(VAL_BUFF,base[0],total)
		case BUFF_SUB_TYPE_DMG:
			//伤害
			total = cfg.GetBuffDmgValue(trigger,target)
			log.Printf("Get buff dmg value = %d",total)
			if total <= 0 {
				log.Printf("get buff dmg value %d error.",total)
				return nil
			}
		case BUFF_SUB_TYPE_CURE:
			//治疗
			total = cfg.GetBuffCureValue(trigger,target)
			log.Printf("Get buff cure value = %d",total)
			if total <= 0 {
				log.Printf("get buff cure value %d error.",total)
				return nil
			}
		case BUFF_SUB_TYPE_STUN:
			//晕
			target.SetState(STUN,1)
		case BUFF_SUB_TYPE_FREEZE:
			//冰冻
			target.SetState(FREEZE,1)
		case BUFF_SUB_TYPE_SILENT:
			//沉默
			target.SetState(SILENT,1)
		case BUFF_SUB_TYPE_ARMOR:
			//霸体
			target.SetState(ARMOR,1)
		case BUFF_SUB_TYPE_FREE:
			//免疫控制
			target.SetState(FREE,1)
		case BUFF_SUB_TYPE_HERO:
			//无敌
			target.SetState(HERO,1)
		case BUFF_SUB_TYPE_UNDEAD:
			//免死
			for i=0;i<BATTLE_PARAM_MAX2;i++ {
				if cfg.Param1[i] <= 0 {
					break
				}
				base = append(base,cfg.Param1[i])
			}
			total = cfg.Param1[0]*target.TakeAtVal(VAL_MAX,HP)/1000
			//有序保存group id
			target.undead = append(target.undead,cfg.Group)
		case BUFF_SUB_TYPE_SHIELD:
			//护盾
			var attr int32
			switch cfg.Param1[0] {
				case 1:
					attr = trigger.TakeAtVal(VAL_MAX,cfg.Param1[1])
				default:
					attr = target.TakeAtVal(VAL_MAX,cfg.Param1[1])
			}
			total = attr*cfg.Param1[2]/1000
			if total <= 0 {
				log.Printf("get buff shield value %d error.",total)
				return nil
			}
			if cfg.Param1[3] == int32(cfg.Sub_type) {
				log.Printf("buff %d delete event can't be oneself.",cfg.Sub_type)
				return nil
			}
			base = append(base,total,cfg.Param1[3],cfg.Param1[4])
			//有序保存group id
			target.shield = append(target.shield,cfg.Group)
		default:
			log.Printf("create buff sub_type %d not found.",cfg.Sub_type)
			return nil
	}

	buff := &Buff_have {
		id:cfg.Id,
		Type:cfg.Type,
		sub_type:cfg.Sub_type,
		group:cfg.Group,
		grade:cfg.Grade,
		tag:cfg.Tag,
		loop_time:cfg.Loop_time,
		next_time:target.area.root_time,
		end_time:target.area.root_time+cfg.End_time,
		level_max:cfg.Level_max,
		level:level,
		level_func:cfg.Level_func,
		total:total,
		base:base,
	}
	//生效
	target.DoBuffEffect(buff)
	//buff结束事件
	target.area.SetEventMap(buff.end_time,0,0)
	return buff
}
//buff结束事件
func (u *Battle_unit)BuffEndEvent(buff *Buff_have) {
	switch buff.sub_type {
		case BUFF_SUB_TYPE_ATTR:
			//返还属性值
			u.ChangeAttr(VAL_BUFF,buff.base[0],-buff.total)
		case BUFF_SUB_TYPE_STUN:
			//状态回滚
			u.SetState(STUN,-1)
		case BUFF_SUB_TYPE_FREEZE:
			//状态回滚
			u.SetState(FREEZE,-1)
		case BUFF_SUB_TYPE_SILENT:
			//状态回滚
			u.SetState(SILENT,-1)
		case BUFF_SUB_TYPE_ARMOR:
			//状态回滚
			u.SetState(ARMOR,-1)
		case BUFF_SUB_TYPE_FREE:
			//状态回滚
			u.SetState(FREE,-1)
		case BUFF_SUB_TYPE_HERO:
			//状态回滚
			u.SetState(HERO,-1)
		case BUFF_SUB_TYPE_UNDEAD:
			//特殊事件 加血
			u.ChangeAttr(VAL,HP,buff.total)
		case BUFF_SUB_TYPE_SHIELD:
			//特殊事件 驱散buff
			u.ClearBuff(3,int8(buff.base[1]),buff.base[2],0)
	}
}
//按规则驱散buff
func (u *Battle_unit)ClearBuff(Type int8,sub_type int8,group int32,level int8) {
	if level <= 0 {
		log.Printf("clear buff level %d error.",level)
		return
	}
	switch Type {
		case 1:
			all := u.GetAllBuffMap()
			for _,v := range all {
				del := make([]int32,0)
				for k1,v1 := range v {
					if v1.Type != sub_type {
						continue
					}
					u.BuffEndEvent(v1)
					del = append(del,k1)
				}
				for _,v1 := range del {
					delete(v,v1)
				}
			}
		case 2:
			all := u.GetBuffMap(sub_type)
			for _,v := range all {
				u.BuffEndEvent(v)
			}
			delete(u.GetAllBuffMap(),sub_type)
		case 3:
			all := u.GetBuffMap(sub_type)
			buff := all[group]
			if buff == nil {
				return
			}
			u.BuffEndEvent(buff)
			delete(all,group)
		case 4:
			all := u.GetBuffMap(sub_type)
			buff := all[group]
			if buff == nil {
				return
			}
			buff.level -= level
			if buff.level > 0 {
				return
			}
			u.BuffEndEvent(buff)
			delete(all,group)
	}
}

func (target *Battle_unit)AddBuff(trigger *Battle_unit,buff_id int32,level int8) {
	if level <= 0 {
		log.Printf("add buff %d level %d error.",buff_id,level)
		return
	}
	log.Printf("add buff %d level %d",buff_id,level)
	cfg := Get_config_buff(buff_id)
	if cfg == nil {
		log.Printf("get config buff %d is not found.",buff_id)
		return
	}
	if target == nil || trigger == nil {
		log.Printf("unit not found.")
		return
	}
	if !target.area.CheckConditions(cfg.Ctype,Build_condition_slice(cfg.Condition),trigger,target) {
		//条件未通过
		log.Printf("add buff check condition failed.%v",cfg.Condition)
		return
	}
	//无敌状态不能添加debuff
	if target.TakeState(HERO) && cfg.Type == 2{
		log.Printf("hero state can't add debuff.")
		return
	}
	//免控状态不能添加控制类buff
	if target.TakeState(FREE) && (cfg.Sub_type == BUFF_SUB_TYPE_STUN || cfg.Sub_type == BUFF_SUB_TYPE_FREEZE || cfg.Sub_type == BUFF_SUB_TYPE_SILENT) {
		log.Printf("free state can't add control buff.")
		return
	}
	//
	//条件全部通过
	bmap := target.GetBuffMap(cfg.Sub_type)
	buff := bmap[cfg.Group]
	if buff != nil {
		//找到同组buff
		if buff.id == buff_id {
			//同id buff
			//叠层 立即生效 并刷新结束时间
			old_level := buff.level
			buff.level += level
			if buff.level > buff.level_max {
				buff.level = buff.level_max
			}
			buff.end_time = target.area.root_time + cfg.End_time
			if buff.sub_type == 11 {
				//盾值回满
				buff.total = buff.base[0]
			}
			target.area.SetEventMap(buff.end_time,0,0)
			target.DoBuffEffect(buff)
			if buff.level != old_level {
				target.PassiveStart(target,POS_ME_BUFF_ADD)
				if buff.tag == 1 {
					target.PassiveStart(target,POS_ME_BUFF_ADD_1)
				}
			}
			return
		} else {
			if cfg.Grade >= buff.grade {
				//替换 先清除 再添加
				target.BuffEndEvent(buff)
				bmap[cfg.Group] = nil
			} else {
				return
			}
		}
	}
	if level > cfg.Level_max {
		level = cfg.Level_max
	}
	//create buff
	buff = cfg.CreateBuff(trigger,target,level)
	if buff == nil {
		log.Printf("create buff error.[%v]",cfg)
		return
	}
	bmap[cfg.Group] = buff
	target.PassiveStart(target,POS_ME_BUFF_ADD)
	if buff.tag == 1 {
		target.PassiveStart(target,POS_ME_BUFF_ADD_1)
	}
}
